<?php
namespace app\api\business;

use app\lib\Arr;
use app\lib\Key;
use app\model\mysql\ProductSku;
use app\model\mysql\ProductSpecValue;
use think\Exception;
use think\facade\Cache;
use think\facade\Log;

class Cart extends Base{

    public function add($params = []) : bool {
        if ($params["id"] <= 0 || $params["num"] <= 0 || $params["user_id"] <= 0) {
            return false;
        }
        try{
            $sku = (new Product())->getSkuWithProduct($params["id"]);
            if (!$sku) {
                return false;
            }
            if ($sku["stock"] < $params["num"]) {
                return false;
            }
            $itemInfo = Cache::hget(Key::getCartKey($params["user_id"]),
                Key::getCartHashKey($params["id"]));
            if ($itemInfo) {
               $itemInfoArr = json_decode($itemInfo, true);
               $itemInfoArr["num"] += $params["num"];
               if ($sku["stock"] < $itemInfoArr["num"]) {
                   return false;
               }
               $itemInfoArr["updatedTime"] = time();
                $result = Cache::hset(Key::getCartKey($params["user_id"]),
                    Key::getCartHashKey($params["id"]), json_encode($itemInfoArr));
                return $result === false ? false : true;
            }

            $data = [
                "sku_id" => $params["id"],
                "title" => $sku["product"]["title"],
                "num" => $params["num"],
                "image" => $sku["product"]["recommend_img"],
                "spec_value_ids" => $sku["spec_value_ids"],
                "createdTime" => time(),
                "updatedTime" => time(),
            ];
            $result = Cache::hset(Key::getCartKey($params["user_id"]),
                Key::getCartHashKey($params["id"]), json_encode($data));
            return $result === false ? false : true;
        }catch (Exception $e){
            Log::error($e);
            return false;
        }
    }

    public function listByUserOrIds($userId = 0, $ids = []) : array {
        if ($userId <= 0) {
            return [];
        }

        $cartItems = [];
        if (!empty($ids)) {
            $cartItems = Cache::hMGet(Key::getCartKey($userId), array_map(function ($value){
                return Key::getCartHashKey($value);
            }, $ids));
        }else{
            $cartItems = Cache::hGetAll(Key::getCartKey($userId));
        }

        if (empty($cartItems)) {
            return [];
        }
        $cartItems = array_map(function ($value){
            return json_decode($value, true);
        }, $cartItems);
        $cartItems = Arr::multiSort("updatedTime", $cartItems, SORT_DESC);
        $specValueIdArr = array_column($cartItems, "spec_value_ids");
        $skuIdArr = array_column($cartItems, "sku_id");
        $specValueIdsBySkuIdArr = array_combine($skuIdArr, $specValueIdArr);
        $specValueIdsBySkuIdArr = array_filter($specValueIdsBySkuIdArr);
        $specValueIdArr = array_filter($specValueIdArr);
        if ($specValueIdArr) {
            $specValueIdArr = explode(",", implode(",", $specValueIdArr));
            $specValueIdArr = array_unique($specValueIdArr);
        }

        try{
            $skuList = (new ProductSku())->field("id, price, stock")->whereIn("id", $skuIdArr)->select();
            $skuList = $skuList->toArray();
            if ($skuList) {
                $skuList = array_combine(array_column($skuList, "id"), $skuList);
            }
            $specValueList = (new ProductSpecValue())->getListByIds($specValueIdArr);

            foreach ($cartItems as $key=>$item) {
                $cartItems[$key]["price"] = isset($skuList[$item["sku_id"]]) ? $skuList[$item["sku_id"]]["price"] : 0;
                $cartItems[$key]["stock"] = isset($skuList[$item["sku_id"]]) ? $skuList[$item["sku_id"]]["stock"] : 0;
                $cartItems[$key]["sku"] = "";
                if (!isset($specValueIdsBySkuIdArr[$item["sku_id"]])) {
                    continue;
                }
                foreach ($specValueList as $value) {
                    if (in_array($value["id"], explode(",", $specValueIdsBySkuIdArr[$item["sku_id"]]))) {
                        $cartItems[$key]["sku"] .= $value["spec"]["name"] . ": ".$value["name"] . " ";
                    }
                }
            }
            return array_values($cartItems);

        }catch (Exception $e){
            Log::error($e);
            return [];
        }

    }

    public function update($params = []) : bool {
        if ($params["id"] <= 0 || $params["num"] <= 0 || $params["user_id"] <= 0) {
            return false;
        }
        try{
            $sku = (new Product())->getSkuWithProduct($params["id"]);
            if (!$sku) {
                return false;
            }
            if ($sku["stock"] < $params["num"]) {
                return false;
            }
            $itemInfo = Cache::hget(Key::getCartKey($params["user_id"]),
                Key::getCartHashKey($params["id"]));
            if (empty($itemInfo)) {
                return false;
            }
            $itemInfoArr = json_decode($itemInfo, true);
            $itemInfoArr["num"] = $params["num"];
            $itemInfoArr["updatedTime"] = time();
            $result = Cache::hset(Key::getCartKey($params["user_id"]),
                Key::getCartHashKey($params["id"]), json_encode($itemInfoArr));

            return $result === false ? false : true;
        }catch (Exception $e){
            Log::error($e);
            return false;
        }
    }

    public function delete($params = []) : bool {
        if ($params["id"] <= 0 || $params["user_id"] <= 0) {
            return false;
        }

        $result = Cache::hDel(Key::getCartKey($params["user_id"]), Key::getCartHashKey($params["id"]));

        return $result === false ? false : true;
    }

    public static function getCartCount($userId = 0) : int {
        if ($userId <= 0) {
            return 0;
        }
        return Cache::hLen(Key::getCartKey($userId));

    }

    public function mHDel($userId, $ids) : bool {
        if (!is_array($ids)) {
            $ids = explode(",", $ids);
        }

        $result = Cache::hDel(Key::getCartKey($userId, ...array_map(function ($value){
            return Key::getCartHashKey($value);
        }, $ids)));

        return $result === false ? false : true;
    }
}